package cn.itsource.user.service.impl;

import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.http.HttpUtil;
import cn.itsource.basic.constant.WxConstants;
import cn.itsource.basic.dto.LoginDto;
import cn.itsource.basic.jwt.JwtUtil;
import cn.itsource.basic.jwt.Payload;
import cn.itsource.basic.util.AjaxResult;
import cn.itsource.system.domain.Permission;
import cn.itsource.system.domain.TMenu;
import cn.itsource.system.mapper.PermissionMapper;
import cn.itsource.system.mapper.TMenuMapper;
import cn.itsource.user.domain.Logininfo;
import cn.itsource.user.domain.User;
import cn.itsource.user.domain.Wxuser;
import cn.itsource.user.mapper.LogininfoMapper;
import cn.itsource.user.mapper.UserMapper;
import cn.itsource.user.mapper.WxuserMapper;
import cn.itsource.user.service.ILogininfoService;
import cn.itsource.basic.service.impl.BaseImpl;
import com.alibaba.fastjson.JSONObject;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * 业务实现类：
 */
@Service
public class LogininfoServiceImpl extends BaseImpl<Logininfo> implements ILogininfoService {
    @Autowired
    private LogininfoMapper logininfoMapper;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private WxuserMapper wxuserMapper;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private TMenuMapper tMenuMapper;
    @Autowired
    private PermissionMapper permissionMapper;

    @Override
    public AjaxResult accountLogin(LoginDto loginDto) {
        //空值校验
        if (StrUtil.isBlank(loginDto.getAccount()) || StrUtil.isBlank(loginDto.getPassword())) {
            throw new RuntimeException(("账号或密码不能为空"));
        }
        //账号校验
        Logininfo logininfo = logininfoMapper.selectByUsername(loginDto.getAccount());
        if (logininfo == null) {
            throw new RuntimeException("账号不存在");
        }
        //密码校验
        if (!logininfo.getPassword().equals(SecureUtil.md5(loginDto.getPassword() + logininfo.getSalt()))) {
            throw new RuntimeException("密码错误");
        }
        //状态校验
        if (logininfo.getState() == 0) {
            throw new RuntimeException("账号已被禁用");
        }


        Map<String, Object> map = loginSuccessJwtHandler(logininfo);

        /*//创建token并将其存入Redis
        String token = IdUtil.randomUUID();
        redisTemplate.opsForValue().set(token, logininfo, 30, TimeUnit.MINUTES);

        //将token和登录信息返回给前端
        Map<String, Object> map = new HashMap<>();
        map.put("token", token);
        logininfo.setPassword(null);
        map.put("logininfo", logininfo);
        System.out.println("987498");*/
        return AjaxResult.me().setResultObj(map);
    }

    @Override
    public AjaxResult wechatLogin(String code) {
        //扫码获取code
        //发送第二个请求
        //组装第二个请求
        String url = WxConstants.GET_ACK_URL.replace("APPID", WxConstants.APPID)
                .replace("SECRET", WxConstants.SECRET)
                .replace("CODE", code);

        //使用hutools的httpUtil发送get请求->相应json数据
        String JsonStr = HttpUtil.get(url);
        //解析json字符串获取openid
        //使用fastJson将json格式字符串转化为json对象 ->accessToken和openid前端跳绑定页面
        JSONObject jsonObject = JSONObject.parseObject(JsonStr);
        String accessToken = jsonObject.getString("access_token");
        String openid = jsonObject.getString("openid");
        //openid查询t_wxuser中的账号
        Wxuser wxuser = wxuserMapper.selectByOpenid(openid);
        //存在则免密登录
        if (wxuser != null) {
            User user = userMapper.selectById(wxuser.getUserId());
            Logininfo logininfo = logininfoMapper.selectById(user.getLogininfoId());
            String token = IdUtil.randomUUID();
            Map<String, Object> map = loginSuccessJwtHandler(logininfo);
            return AjaxResult.me().setResultObj(map);
        }
        //不存在就相应给前端openid和accessToken
        String params = "?accessToken=" + accessToken + "&openid=" + openid;
        return AjaxResult.me().setResultObj(params).setSuccess(false);
    }

    @Override
    public AjaxResult wechatBinder(Map<String, String> map) {
        //空值校验
        String phone = map.get("phone");
        String verifyCode = map.get("verifyCode");
        String accessToken = map.get("accessToken");
        String openid = map.get("openid");
        if (StrUtil.isBlank(phone) || StrUtil.isBlank(verifyCode)) {
            throw new RuntimeException("手机号或验证码不能为空");
        }

        Object obj = redisTemplate.opsForValue().get("binder:" + phone);
        //校验验证码是否过期
        if (obj == null) {
            throw new RuntimeException("验证码已过期");
        }
        //校验验证码是否正确
        if (!obj.toString().split(":")[0].equals(verifyCode)) {
            throw new RuntimeException("验证码错误");
        }
        //组装发送第三个请求
        String url = WxConstants.GET_USER_URL.replace("ACCESS_TOKEN", accessToken)
                .replace("OPENID", openid);
        String JsonStr = HttpUtil.get(url);

        //通过该手机号查找user表中的对应数据
        User user = userMapper.selectByPhone(phone);

        //当user为空时
        if (user == null) {
            //构建User对象
            user = PhoneToUser(phone);
            //构建Logininfo对象
            Logininfo logininfo = new Logininfo();
            BeanUtils.copyProperties(user,logininfo);
            logininfo.setType(1);

            //存入数据库
            //先存入logininfo
            logininfoMapper.insert(logininfo);
            //为user设置logininfoId后将user存入数据库
            user.setLogininfoId(logininfo.getId());
            userMapper.insert(user);

        }
        if (user.getState()==0){
            throw new RuntimeException("账号已被禁用");
        }

        //添加数据库
        //构建Wxuser对象
        //先在数据库通过openid查找是否存在
        Wxuser wxuser = wxuserMapper.selectByOpenid(openid);
        if (wxuser == null){
            wxuser = JsonStrToWxuser(JsonStr);

            //为wxuser设置userId后将wxuser存入数据库
            wxuser.setUserId(user.getId());
            wxuserMapper.insert(wxuser);
        }else{
            //设置user_id并修改数据库信息
            wxuser.setUserId(user.getId());
            wxuserMapper.update(wxuser);
        }



        //免密登录
        Logininfo logininfo = logininfoMapper.selectById(user.getLogininfoId());
        Map<String, Object> map2 = new HashMap<>();
        String token = IdUtil.randomUUID();
        redisTemplate.opsForValue().set(token, logininfo, 30, TimeUnit.MINUTES);
        map2.put("token", token);
        logininfo.setPassword(null);
        map2.put("logininfo", logininfo);


        return new AjaxResult().me().setResultObj(map2);
    }

    private User PhoneToUser(String phone) {
        User user = new User();
        user.setUsername(phone);
        user.setPhone(phone);
        String password = RandomUtil.randomNumbers(6);
        String salt = RandomUtil.randomString(32);
        String MD5Pwd = SecureUtil.md5(password + salt);
        user.setSalt(salt);
        user.setPassword(MD5Pwd);
        user.setState(1);
        return user;
    }

    private Wxuser JsonStrToWxuser(String jsonStr) {
        JSONObject jsonObject = JSONObject.parseObject(jsonStr);
        Wxuser wxuser = new Wxuser();
        wxuser.setHeadimgurl(jsonObject.getString("headimgurl"));
        wxuser.setNickname(jsonObject.getString("nickname"));
        wxuser.setOpenid(jsonObject.getString("openid"));
        wxuser.setUnionid(jsonObject.getString("unionid"));
        return wxuser;

    }

    //LogininfoServiceImpl
    private Map<String,Object> loginSuccessJwtHandler(Logininfo logininfo){
        Map<String,Object> map = new HashMap<>();
        Payload payload = new Payload();
        //设置payload中的logininfo参数
        payload.setLogininfo(logininfo);
        map.put("logininfo",logininfo);
        //如果当前登录人是管理员就获取权限信息和菜单信息
        if (logininfo.getType()==0){
            //获取菜单信息
            List<TMenu> menuList = logininfoMapper.selectMenusByLogininfoId(logininfo.getId());
            payload.setMenus(menuList);
            map.put("menus",menuList);

            //获取权限信息
            List<String> permissions = logininfoMapper.selectPermissionsByLogininfoId(logininfo.getId());
            payload.setPermissions(permissions);
            map.put("permissions",permissions);

        }
        //将payload转换为jwtToken
        String jwtToken = JwtUtil.generateToken(payload);
        map.put("token",jwtToken);
        return map;



    }







}

